package com.gitee.wsl.android.ext.device

//package dev.utils.app.assist;

import android.annotation.SuppressLint
import android.content.Context
import android.hardware.Sensor
import android.hardware.SensorEvent
import android.hardware.SensorEventListener
import android.hardware.SensorManager
import android.os.Handler
import android.os.Message
import com.gitee.wsl.android.ext.ApplicationInit.application
import timber.log.Timber
import kotlin.math.atan2
import kotlin.math.roundToInt

/**
 * detail: 屏幕传感器辅助类 ( 监听是否横竖屏 )
 * @author Ttt
 */
class ScreenSensor {

    // ==================
    // = 重力传感器监听对象 =
    // ==================
    // 传感器管理对象
    private var mSensorManager: SensorManager? = null

    // 重力传感器
    private var mSensor: Sensor? = null

    // 重力传感器监听事件
    private var mListener: OrientationSensorListener? = null

    // ===========================================
    // = 重力传感器监听对象 ( 改变方向后, 判断参数不同 ) =
    // ===========================================
    // 传感器管理对象 ( 切屏后 )
    private var mSensorManagerChange: SensorManager? = null

    // 重力传感器监听事件 ( 切屏后 )
    private var mListenerChange: OrientationSensorChangeListener? = null

    // =======
    // = 常量 =
    // =======
    // 方向未知常量
    private val ORIENTATION_UNKNOWN = -1

    /**
     * 是否允许切屏
     * @return `true` 允许, `false` 不允许
     */
    // =======
    // = 变量 =
    // =======
    // 是否允许切屏
    var isAllowChange = false
        private set

    /**
     * 是否竖屏
     * @return `true` 竖屏, `false` 非竖屏
     */
    // 是否是竖屏
    var isPortrait = true
        private set

    // 回调操作
    private var mHandler: Handler? = null

    /**
     * 角度处理 Handler
     */
    @SuppressLint("HandlerLeak")
    private val mRotateHandler: Handler = object : Handler() {
        override fun handleMessage(msg: Message) {
            when (msg.what) {
                CHANGE_ORIENTATION_WHAT -> {
                    // 获取角度
                    val rotation = msg.arg1
                    // =
                    Timber.d( "当前角度: %s", rotation)
                    // 判断角度
                    if (rotation in 46..134) {
                        // 横屏 ( 屏幕对着别人 )
                        Timber.d( "切换成横屏 ( 屏幕对着自己 )")
                        // =
                        if (isPortrait) {
                            isPortrait = false
                            if (mHandler != null) {
                                val vMsg = Message()
                                vMsg.what = CHANGE_ORIENTATION_WHAT
                                vMsg.arg1 = 1
                                mHandler!!.sendMessage(vMsg)
                            }
                        }
                    } else if (rotation in 136..224) {
                        // 竖屏 ( 屏幕对着别人 )
                        Timber.d( "切换成竖屏 ( 屏幕对着别人 )")
                        // =
                        if (!isPortrait) {
                            isPortrait = true
                            if (mHandler != null) {
                                val vMsg = Message()
                                vMsg.what = CHANGE_ORIENTATION_WHAT
                                vMsg.arg1 = 2
                                mHandler!!.sendMessage(vMsg)
                            }
                        }
                    } else if (rotation in 226..314) {
                        // 横屏 ( 屏幕对着自己 )
                        Timber.d( "切换成横屏 ( 屏幕对着自己 )")
                        // =
                        if (isPortrait) {
                            isPortrait = false
                            if (mHandler != null) {
                                val vMsg = Message()
                                vMsg.what = CHANGE_ORIENTATION_WHAT
                                vMsg.arg1 = 1
                                mHandler!!.sendMessage(vMsg)
                            }
                        }
                    } else if ((rotation in 316..359 || rotation > 0) && rotation < 45) {
                        // 竖屏 ( 屏幕对着自己 )
                        Timber.d( "切换成竖屏 ( 屏幕对着自己 )")
                        // =
                        if (!isPortrait) {
                            isPortrait = true
                            if (mHandler != null) {
                                val vMsg = Message()
                                vMsg.what = CHANGE_ORIENTATION_WHAT
                                vMsg.arg1 = 2
                                mHandler!!.sendMessage(vMsg)
                            }
                        }
                    } else {
                        Timber.d( "其他角度: %s", rotation)
                    }
                }
            }
        }
    }
    // =
    /**
     * 初始化操作
     * @param handler 回调 [Handler]
     */
    private fun initialize(handler: Handler) {
        mHandler = handler
        // 注册重力感应器, 监听屏幕旋转
        mSensorManager = application.sensorManager
        mListener = OrientationSensorListener()
        // 根据 旋转之后、点击全屏之后 两者方向一致, 激活 SensorManager
        mSensorManagerChange = application.sensorManager
        mListenerChange = OrientationSensorChangeListener()
        // 设置传感器
        mSensor = mSensorManager!!.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
    }

    /**
     * 开始监听
     * @param handler 回调 [Handler]
     * @return `true` success, `false` fail
     */
    fun start(handler: Handler): Boolean {
        isAllowChange = true
        try {
            Timber.d( "start orientation listener.")
            // 初始化操作
            initialize(handler)
            // 监听重力传感器
            mSensorManager!!.registerListener(mListener, mSensor, SensorManager.SENSOR_DELAY_UI)
            return true
        } catch (e: Exception) {
            Timber.d( e, "start")
        }
        return false
    }

    /**
     * 停止监听
     * @return `true` success, `false` fail
     */
    fun stop(): Boolean {
        isAllowChange = false
        Timber.d( "stop orientation listener.")
        try {
            mSensorManager!!.unregisterListener(mListener)
        } catch (ignored: Exception) {
        }
        try {
            mSensorManagerChange!!.unregisterListener(mListenerChange)
        } catch (ignored: Exception) {
        }
        return true
    }
    // =
    /**
     * detail: 重力传感器监听事件
     * @author Ttt
     */
    internal inner class OrientationSensorListener : SensorEventListener {
        override fun onAccuracyChanged(
            sensor: Sensor,
            accuracy: Int
        ) {
        }

        override fun onSensorChanged(event: SensorEvent) {
            val values = event.values
            var orientation = ORIENTATION_UNKNOWN
            val X = -values[DATA_X]
            val Y = -values[DATA_Y]
            val Z = -values[DATA_Z]
            val magnitude = X * X + Y * Y
            // Don't trust the angle if the magnitude is small compared to the y value
            if (magnitude * 4 >= Z * Z) {
                // 屏幕旋转时
                val OneEightyOverPi = 57.29578f
                val angle = atan2(-Y, X) * OneEightyOverPi
                orientation = 90 - angle.roundToInt()
                // normalize to 0 - 359 range
                while (orientation >= 360) {
                    orientation -= 360
                }
                while (orientation < 0) {
                    orientation += 360
                }
            }
            mRotateHandler.obtainMessage(
                CHANGE_ORIENTATION_WHAT, orientation, 0
            ).sendToTarget()
        }
    }

    /**
     * detail: 重力传感器监听事件 ( 切屏后 )
     * @author Ttt
     */
    internal inner class OrientationSensorChangeListener : SensorEventListener {
        override fun onAccuracyChanged(
            sensor: Sensor,
            accuracy: Int
        ) {
        }

        override fun onSensorChanged(event: SensorEvent) {
            val values = event.values
            var orientation = ORIENTATION_UNKNOWN
            val X = -values[DATA_X]
            val Y = -values[DATA_Y]
            val Z = -values[DATA_Z]
            val magnitude = X * X + Y * Y
            // Don't trust the angle if the magnitude is small compared to the y value
            if (magnitude * 4 >= Z * Z) {
                // 屏幕旋转时
                val OneEightyOverPi = 57.29578f
                val angle = atan2(-Y, X) * OneEightyOverPi
                orientation = 90 - angle.roundToInt()
                // normalize to 0 - 359 range
                while (orientation >= 360) {
                    orientation -= 360
                }
                while (orientation < 0) {
                    orientation += 360
                }
            }
            if (orientation in 226..314) {
                // 检测到当前实际是横屏
                if (!isPortrait) {
                    mSensorManager!!.registerListener(
                        mListener,
                        mSensor,
                        SensorManager.SENSOR_DELAY_UI
                    )
                    mSensorManagerChange!!.unregisterListener(mListenerChange)
                }
            } else if (orientation in 316..359 || orientation in 1..44) {
                // 检测到当前实际是竖屏
                if (isPortrait) {
                    mSensorManager!!.registerListener(
                        mListener,
                        mSensor,
                        SensorManager.SENSOR_DELAY_UI
                    )
                    mSensorManagerChange!!.unregisterListener(mListenerChange)
                }
            }
        }
    }

    companion object {

        // 坐标索引常量
        private const val DATA_X = 0
        private const val DATA_Y = 1
        private const val DATA_Z = 2

        // 触发屏幕方向改变回调
        const val CHANGE_ORIENTATION_WHAT = 9919
    }
}

val globalSensorManager:SensorManager by lazy { application.sensorManager }

val Context.sensorManager:SensorManager
    get() = getSystemService(SensorManager::class.java)